﻿#include <utility>

//
// Created by hujin on 2020/10/6.
//

#ifndef C_MIPS_CMPLR_AST_FUNCTION_H
#define C_MIPS_CMPLR_AST_FUNCTION_H

#include "ast.h"

class FunctionHeadNode : public  ASTNode {
public:
	std::string name;
	bool retInt;
	FunctionHeadNode(bool retInt, std::string& name) : retInt(retInt), name(std::move(name)) {}
};

class FunctionNode : public  ASTNode {
protected:
	FunctionHeadNode* head;
	ParamsNode* paramsNode;
	BodyNode* statements;
public:
	FunctionNode(FunctionHeadNode* functionHead, ParamsNode* paramsNode, BodyNode* statements) : head(
		functionHead), paramsNode(paramsNode), statements(statements) {};
    bool checkError(SymbolTable *table) override;


    virtual void genCode(Synthesizer *syn, MemoryAllocator *mem);
};

class FunctionVoidNode : public  FunctionNode {
	std::string name;
public:
	FunctionVoidNode(std::string& name, ParamsNode* paramsNode, BodyNode* statements) : name(std::move(name)),
		FunctionNode(nullptr, paramsNode, statements) {}
    bool checkError(SymbolTable *table) override;

	void genCode(Synthesizer *syn, MemoryAllocator *mem) override;

};

class BodyNode : public  ASTNode {
	CnstListNode* cnstDef;
	VarListNode* varDef;
	StatListNode* statements;

public:
	BodyNode(CnstListNode* cnstDef, VarListNode* varDef, StatListNode* statements) : cnstDef(cnstDef), varDef(varDef),
		statements(statements) {}

    StatListNode *getStatements() const {
        return statements;
    }

    void genCode(Synthesizer *out, MemoryAllocator *allocator) ;
};

class ParamsNode : public  ASTNode {
	std::vector<std::pair<bool, std::string>> params;
	std::vector<Identifier_Data> data;
public:
	explicit ParamsNode(std::vector<std::pair<bool, std::string>>& params) : params(std::move(params)) {}
	void addToTable(SymbolTable* table) override;

	void putFunctionToTable(SymbolTable* table, FunctionHeadNode* headNode);
	void putVoidFuncToTable(SymbolTable* table, std::string& name);

    const std::vector<std::pair<bool, std::string>> &getParams() const;


    void genCodeRead(Synthesizer *syn, MemoryAllocator *memNew);
};


std::string getLabelName(std::string func);
#endif //C_MIPS_CMPLR_AST_FUNCTION_H
